// Rook.cpp
//
// Created By: Jeremy Butler
// Created On: 11-Apr-2011

#include "Rook.h"
#include "Board.h"
#include "UnitTest.h"
#include "ChessController.h"
#include <sstream>
using namespace std;

Rook::Rook() : Piece() {
  return;
}

Rook::Rook(const Color _color) : Piece(_color, ROOK){
  return;
}

Rook::Rook(const Rook & other) : Piece(other) {
  return;
}

Rook * Rook::Clone() const{
  return new Rook(*this);
}

Rook::~Rook(){
  return;
}

string Rook::ToString() const{
  stringstream str;

  string sColor;
  if(color == WHITE)
    sColor = "White";
  else if(color == BLACK)
    sColor = "Black";
  else
    sColor = "Colorless";

  str << sColor << " Rook";

  return str.str();
}

set<Location> Rook::GetValidMoves(const Board & board, int row, int col, bool AllMoves) const{
  set<Location> validMoves;

  GetMoves1(board, row, col, validMoves);
  GetMoves2(board, row, col, validMoves);
  GetMoves3(board, row, col, validMoves);
  GetMoves4(board, row, col, validMoves);

  if(!AllMoves)
    board.RemoveCheckMoves(validMoves,row,col);

  return validMoves;
}

void Rook::GetMoves1(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    int i = 1;
    while(board(row+i,col) == NULL){
      location.Set(col,row+i);
      validMoves.insert(location);
      i++;
    }
    if(board(row+i,col)->GetColor() != GetColor()){
      location.Set(col,row+i);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void Rook::GetMoves2(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    int i = 1;
    while(board(row-i,col) == NULL){
      location.Set(col,row-i);
      validMoves.insert(location);
      i++;
    }
    if(board(row-i,col)->GetColor() != GetColor()){
      location.Set(col,row-i);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void Rook::GetMoves3(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    int i = 1;
    while(board(row,col+i) == NULL){
      location.Set(col+i,row);
      validMoves.insert(location);
      i++;
    }
    if(board(row,col+i)->GetColor() != GetColor()){
      location.Set(col+i,row);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}
void Rook::GetMoves4(const Board & board, int row, int col,
		       set<Location> & validMoves) const{
  Location location;
  try{
    int i = 1;
    while(board(row,col-i) == NULL){
      location.Set(col-i,row);
      validMoves.insert(location);
      i++;
    }
    if(board(row,col-i)->GetColor() != GetColor()){
      location.Set(col-i,row);
      validMoves.insert(location);
    }
  }catch(InvalidArgumentException e){
    //cout << e.GetMessage() << endl;
  }
}

bool Rook::Test(ostream & os){
  bool success = true;

  ChessView view;
  ChessController controller(view,0);

  controller.SetView(&view);
  view.SetController(&controller);

  controller.LoadGame("games/rookTest.xml");

  set<Location> moves;

  moves = controller.model->GetValidMoves(7,0);

  TEST(moves.size() == 10);

  moves = controller.model->GetValidMoves(6,4);

  TEST(moves.size() == 5);

  moves = controller.model->GetValidMoves(4,2);

  TEST(moves.size() == 14);

  return success;
}
